/* License Notice:
**
** This program is free software: you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation, either version 3 of the License, or
**    (at your option) any later version.
** This program is distributed in the hope that it will be useful,
**   but WITHOUT ANY WARRANTY; without even the implied warranty of
**   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
**   GNU General Public License for more details.
** You should have received a copy of the GNU General Public License
**   along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

/**
 * @file music_sources.cpp
 * @author TooOld2Rock'nRoll
 * @see music_sources.hpp
 */
/*---- Includes ----*/
#include "audio/music_sources.hpp"

#include "toolbox/debug.h"


/*---- Global Variables ----*/


/*---- Methods Implementation ----*/
/**
 * @brief Loads a audio file as a Music sound source.
 *
 * @param file_path - the audio file path.
 *
 * @throws std::invalid_argument - in case the file path is null.
 * @throws std::runtime_error - in case loading the file is not possible.
 */
UndecodedFileSource::UndecodedFileSource (const char *file_path) : AudioSourceData()
{
    _debug (TRACE, "::%s (file='%s')", __FUNCTION__, file_path);

    if (!file_path)
        throw std::invalid_argument (fmt::format ("{0}:{1} - A audio file is necessary, file path is null!", __LINE__, __FILE__));

    this->p_native_audio_data = Mix_LoadMUS (file_path);
    if (!this->p_native_audio_data)
        throw std::runtime_error (fmt::format ("{0}:{1} - The '{2}' file can't be loaded, error:\r\n{3}",
                                               __LINE__, __FILE__, file_path, Mix_GetError()));

    this->d_length =  Mix_MusicDuration (this->p_native_audio_data);
}//End Constructor

/**
 * @brief Destructor.
 */
UndecodedFileSource::~UndecodedFileSource ()
{
    _debug (TRACE, "::%s ()", __FUNCTION__);

    if (this->p_native_audio_data)
        Mix_FreeMusic (this->p_native_audio_data);
};//End destructor


/**
 * @brief Creates a Music audio source that streams data to the mixer.
 */
MusicStreamSource::MusicStreamSource () : AudioSourceData()
{
    _debug (TRACE, "::%s ()", __FUNCTION__);

    //this is a very simple bridge from SDL_Mixer callback to our class callback.
    //so it makes sense to create it as a lambda function pointer instead of formally creating an access point.
    this->p_native_audio_data = [](void *obj_musicStream, Uint8 *buffer, int len)
    {
        MusicStreamSource *obj_this = (MusicStreamSource *)obj_musicStream;

        _debug (VERBOSE, "::%s (buffer_len=%u)", __FUNCTION__, len);

        if (obj_this)
            obj_this->_fill_stream_cb (buffer, len);
        else
            _debug (ERROR, "MusicStreamSource seams to be null, can't call the callback!");
    };//end stream callback
}//End Constructor


